<template>
	<div class="uploadWrapper">
		<vuedraggable v-model="imgList" :class="{ single: isSingle, maxHidden: isMaxHidden }" class="vue-draggable" draggable=".draggable-item" tag="ul" @end="onDragEnd" @start="onDragStart">
			<!-- 拖拽元素 -->
			<li v-for="(item, index) in imgList" :key="item + index" :style="{ width: width, height: height }" class="draggable-item">
				<template v-if="fileType === 'img'">
					<el-image :preview-src-list="[item]" :src="item" :z-index="9999"></el-image>
					<div class="shadow" @click="onRemoveHandler(index)">
						<i class="el-icon-delete"></i>
					</div>
				</template>
				<template v-if="fileType === 'video'">
					<video-player
						ref="videoPlayer"
						:options="{
							height,
							autoplay: false,
							muted: false,
							loop: false,
							fluid: true,
							sources: [
								{
									type: 'video/mp4',
									src: item,
								},
							],
							autoplay: false,
							controls: true,
						}"
						:playsinline="true"
					></video-player>
					<div class="shadow" @click="onRemoveHandler(index)">
						<i class="el-icon-delete"></i>
					</div>
				</template>
				<template v-if="fileType === 'glb'">
					<el-image>
						<div slot="error" class="glb">
							<el-button type="primary" @click="$emit('preview', item)">预览模型</el-button>
						</div>
					</el-image>
					<div class="shadow" @click="onRemoveHandler(index)">
						<i class="el-icon-delete"></i>
					</div>
				</template>
			</li>
			<!-- 上传按钮 -->

			<div class="mb-[20px]">
				<el-upload
					ref="uploadRef"
					:accept="accept"
					action=""
					:http-request="httpRequest"
					:before-upload="beforeUpload"
					:headers="headers"
					:limit="limit"
					:multiple="!isSingle"
					:on-exceed="onExceed"
					:on-success="onSuccessUpload"
					:show-file-list="false"
					:style="{ width: width, height: height }"
					class="uploadBox"
				>
					<div class="uploadIcon">
						<slot>
							<i class="el-icon-plus">
								<div v-if="isUploading" class="uploading">正在上传...</div>
							</i>
						</slot>
					</div>
				</el-upload>
			</div>
		</vuedraggable>
		<div v-if="progressTotal > 0" class="el-loading-mask w-full fixed left-0 right-0" style="background-color: rgba(0, 0, 0, 0.1)">
			<div class="el-loading-spinner">
				<i class="el-icon-loading"></i>
				<p class="el-loading-text">正在上传中,当前进度:{{ progressTotal }}%</p>
			</div>
		</div>
		<Avatar ref="avatar" @image="updateImage" />
	</div>
</template>

<script>
import vuedraggable from 'vuedraggable';
import { getToken } from '@/utils/auth'; // 获取token，用于后端接口登录校验，根据公司的业务自行移除或替换就行
import { validImgUpload } from '@/utils/validate';
import lrz from 'lrz'; // 前端图片压缩插件
import tools from '@/utils/tools';
import 'video.js/dist/video-js.css';
import Avatar from './compoennts/avatar';
export default {
	name: 'LImgUpload',
	components: { vuedraggable, Avatar },
	props: {
		// 图片数据(图片url组成的数组) 通过v-model传递
		value: {
			type: [Array, String],
			default() {
				return [];
			},
		},
		//可选文件格式
		accept: {
			type: String,
			default: '.jpg,.jpeg,.png,.gif',
		},
		// 限制上传的图片数量
		limit: {
			type: Number,
			default: 99,
		},
		// 限制上传图片的文件大小(kb)
		size: {
			type: Number,
			default: 4000,
		},
		// 是否是单图上传(单图上传就是已传图片和上传按钮重叠)
		isSingle: {
			type: Boolean,
			default: false,
		},
		// 是否使用图片压缩
		useCompress: {
			type: Boolean,
			default: false,
		},
		// 图片显示的宽度
		width: {
			type: String,
			default: '100%',
		},
		// 图片显示的高度(px)
		height: {
			type: String,
			default: '100px',
		},
		//文件类型
		fileType: {
			type: String,
			default: 'img',
		},
		//裁剪图片
		cutting: {
			type: Boolean,
			default: false,
		},
	},

	data() {
		return {
			uploadImgUrl: process.env.VUE_APP_BASE_API + '/common/upload', // 上传的图片服务器地址
			headers: {
				Authorization: 'Bearer ' + getToken(),
			},

			isUploading: false, // 正在上传状态
			isFirstMount: true, // 控制防止重复回显
			imgList: [],
			loading: false,
			progressTotal: 0,
		};
	},

	computed: {
		// 控制达到最大限制时隐藏上传按钮
		isMaxHidden() {
			return this.imgList.length >= this.limit;
		},
		single() {
			return this.limit === 1 || this.isSingle;
		},
	},

	watch: {
		value: {
			handler(val) {
				//当弹窗组件有dom的时候才会立即执行里面的方法
				this.$nextTick(() => {
					//单张图片
					console.log(val, 'val');
					if (this.limit === 1 || (this.isSingle && val)) {
						this.imgList = Array.isArray(val) ? val : val ? [val] : [];
						this.syncElUpload();
						return;
					}
					//多张图片
					if (Array.isArray(val) && this.value.length > 0) {
						this.imgList = val;
						if (this.isFirstMount) {
							this.syncElUpload();
						}
						return;
					}
					this.imgList = [];
				});
			},
			deep: true,
		},
	},

	methods: {
		httpRequest(file) {
			const formData = new FormData();
			formData.append('file', file.file);
			return this.$request.post('/common/upload', formData, {
				timeout: 36000000,
				onUploadProgress: (progressEvent) => {
					this.progressTotal = Number(((progressEvent.loaded / progressEvent.total) * 100).toFixed(2));
				},
			});
		},
		syncElUploads(val) {
			this.imgList = val;
			this.syncElUpload();
		},
		// 同步el-upload数据
		syncElUpload(val) {
			const imgList = val || this.imgList;
			this.$refs.uploadRef.uploadFiles = imgList.map((v, i) => {
				return {
					name: 'pic' + i,
					url: v,
					status: 'success',
					uid: tools.createUniqueString(),
				};
			});
			this.isFirstMount = false;
		},
		// 上传图片之前
		beforeUpload(file) {
			this.isFirstMount = false;
			if (this.useCompress) {
				// 图片压缩
				return new Promise((resolve, reject) => {
					lrz(file, { width: 1920 })
						.then((rst) => {
							file = rst.file;
						})
						.always(() => {
							if (validImgUpload(file, this.size)) {
								this.isUploading = !this.cutting;
								resolve();
							} else {
								reject(new Error());
							}
						});
				});
			} else {
				if (validImgUpload(file, this.size)) {
					this.isUploading = !this.cutting;
					return true;
				} else {
					return false;
				}
			}
		},
		// 上传完单张图片
		onSuccessUpload(res) {
			// 这里需要根据你自己的接口返回数据格式和层级来自行编辑
			console.log(res);
			setTimeout(() => {
				if (res.data) {
					if (this.cutting) {
						this.isUploading = false;
						this.progressTotal = 0;
						this.$refs.avatar.editCropper(res.data.url);
						return;
					}
					// 判断接口上传成功
					this.updateImage(res.data);
				} else {
					// 判断接口上传失败
					this.syncElUpload();
					this.$message({ type: 'error', message: res.msg });
				}
				this.progressTotal = 0;
				this.isUploading = false;
			}, 1000);
		},
		updateImage(data) {
			// 判断接口上传成功
			if (this.imgList.length < this.limit) {
				// 未超限时，把接口返回的图片url地址添加到imgList
				this.imgList.push(data.url);
				if (this.single) {
					this.$emit('input', data.url);
				} else {
					this.$emit('input', [...this.imgList]);
				}
			}
		},
		// 移除单张图片
		onRemoveHandler(index) {
			this.$confirm('确定删除吗?', '提示', {
				confirmButtonText: '确定',
				cancelButtonText: '取消',
				type: 'warning',
			})
				.then(() => {
					this.imgList = this.imgList.filter((v, i) => {
						return i !== index;
					});
					if (this.single) {
						this.$emit('input', null);
					} else {
						this.$emit('input', this.imgList);
					}
				})
				.catch(() => {});
		},
		// 超限
		onExceed() {
			this.$refs.uploadRef.abort(); // 取消剩余接口请求
			this.syncElUpload();
			this.$message({
				type: 'warning',
				message: `图片超限，最多可上传${this.limit}张图片`,
			});
		},
		onDragStart(e) {
			e.target.classList.add('hideShadow');
		},
		onDragEnd(e) {
			e.target.classList.remove('hideShadow');
		},
	},
};
</script>

<style lang="scss" scoped>
.uploadWrapper {
	::v-deep {
		.el-progress__text {
			font-size: 12px !important;
		}
		.video-player,
		.video-js.vjs-fluid,
		.video-js.vjs-16-9,
		.video-js.vjs-4-3 {
			height: 100%;
		}
		.video-js .vjs-big-play-button {
			height: 20px;
			width: 20px;
			line-height: 20px;
			font-size: 14px;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
		}
		.vjs-error .vjs-error-display .vjs-modal-dialog-content {
			font-size: 14px !important;
		}
		.vjs-error .vjs-error-display:before {
			display: none;
		}
	}
}
::v-deep .el-upload {
	width: 100%;
	height: 100%;
}

::v-deep .glb {
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
}

// 上传按钮
.uploadIcon {
	width: 100%;
	height: 100%;
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px dashed #c0ccda;
	//background-color: #fbfdff;
	border-radius: 6px;
	font-size: 20px;
	color: #999;

	.limitTxt,
	.uploading {
		position: absolute;
		bottom: 10%;
		left: 0;
		width: 100%;
		font-size: 14px;
		text-align: center;
	}
}

// 拖拽
.vue-draggable {
	display: flex;
	flex-wrap: wrap;

	.uploadBox {
		margin: 0 auto;
	}

	.draggable-item {
		margin-right: 5px;
		margin-bottom: 5px;
		border: 1px solid #ddd;
		border-radius: 6px;
		position: relative;
		overflow: hidden;

		.el-image {
			width: 100%;
			height: 100%;
		}

		.shadow {
			position: absolute;
			top: 0;
			right: 0;
			background-color: rgba(0, 0, 0, 0.5);
			opacity: 0;
			transition: opacity 0.3s;
			color: #fff;
			font-size: 20px;
			line-height: 20px;
			padding: 2px;
			cursor: pointer;
		}

		&:hover {
			.shadow {
				opacity: 1;
			}
		}
	}

	&.hideShadow {
		.shadow {
			display: none;
		}
	}

	&.single {
		overflow: hidden;
		position: relative;

		.draggable-item {
			position: absolute;
			left: 0;
			top: 0;
			z-index: 1;
		}
	}

	&.maxHidden {
		.uploadBox {
			display: none;
		}
	}
}

// el-image
.el-image-viewer__wrapper {
	.el-image-viewer__mask {
		opacity: 0.8;
	}

	.el-icon-circle-close {
		color: #fff;
	}
}
</style>
